﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;

namespace FRS.ExceptionLog
{
    public class ExceptionLogRecorder
    {
        /// <summary>
        /// @Author : https://www.cnblogs.com/server126/
        /// @Description: 将异常写入文件
        /// </summary>
        /// <param name="ex">异常</param>
        /// <param name="exceptionMessages">异常信息</param>
        public static void WriteExceptionLog(Exception ex, params string[] exceptionMessages)
        {
            if (ex == null)
                return;                         //ex = null 返回
            StreamWriter writer = null;
            DateTime dt = DateTime.Now;       // 设置日志时间
            string time = dt.ToString("yyyy-mm-dd HH:mm:ss"); //年-月-日 时：分：秒
            string LogName = "Log.log";       //日志名称
            string LogPath = ConfigurationManager.AppSettings["ExceptionLogPath"];   //日志存放路径
            string Log = LogPath + LogName;   //路径 + 名称
            if (!File.Exists(Log))             //是否存在
            {
                Directory.CreateDirectory(LogPath);   //创建文件夹
                writer = File.CreateText(Log);     // 创建日志
            }
            else
            {
                writer = File.AppendText(Log);         //追加，添加错误信息；
            }
            writer.WriteLine(time);
            writer.WriteLine(ex.Message);
            writer.WriteLine("异常信息：" + ex.ToString());
            writer.WriteLine("异常堆栈：" + ex.StackTrace.ToString());
            foreach (string errorMessage in exceptionMessages)
            {
                writer.WriteLine(errorMessage);
            }
            writer.WriteLine("\r\n--------------------------------------\r\n");
            writer.Flush();
            writer.Dispose();
        }

        /// <summary>
        /// @Author:      HTL
        /// @Email:       Huangyuan413026@163.com
        /// @DateTime:    2015-06-03 19:54:49
        /// @Description: 获取当前堆栈的上级调用方法列表,直到最终调用者,只会返回调用的各方法,而不会返回具体的出错行数，可参考：微软真是个十足的混蛋啊！让我们跟踪Exception到行把！（不明真相群众请入） 
        /// </summary>
        /// <returns>堆栈跟踪模型名</returns>
        private static string GetStackTraceModelName()
        {
            //当前堆栈信息
            System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
            System.Diagnostics.StackFrame[] sfs = st.GetFrames();
            //过虑的方法名称,以下方法将不会出现在返回的方法调用列表中
            string _filterdName = "ResponseWrite,ResponseWriteError,";
            string _fullName = string.Empty, _methodName = string.Empty;
            for (int i = 1; i < sfs.Length; ++i)
            {
                //非用户代码,系统方法及后面的都是系统调用，不获取用户代码调用结束
                if (System.Diagnostics.StackFrame.OFFSET_UNKNOWN == sfs[i].GetILOffset()) break;
                _methodName = sfs[i].GetMethod().Name;//方法名称
                //sfs[i].GetFileLineNumber();//没有PDB文件的情况下将始终返回0
                if (_filterdName.Contains(_methodName)) continue;
                _fullName = _methodName + "()->" + _fullName;
            }
            st = null;
            sfs = null;
            _filterdName = _methodName = null;
            return _fullName.TrimEnd('-', '>');
        }

        /// <summary>
        /// 写一个自定义的异常信息
        /// </summary>
        /// <param name="selfDefineErrorString">自定义异常信息</param>
        public static void WriteSelfDefineErrorLog(String selfDefineErrorString)
        {
            StreamWriter writer = null;
            DateTime dt = DateTime.Now;       // 设置日志时间
            string time = dt.ToString("yyyy-mm-dd HH:mm:ss"); //年-月-日 时：分：秒
            string LogName = "Log.log";       //日志名称
            string LogPath = ConfigurationManager.AppSettings["ExceptionLogPath"];   //日志存放路径
            string Log = LogPath + LogName;   //路径 + 名称
            if (!File.Exists(Log))             //是否存在
            {
                Directory.CreateDirectory(LogPath);   //创建文件夹
                writer = File.CreateText(LogName);     // 创建日志
            }
            else
            {
                writer = File.AppendText(Log);         //追加，添加错误信息；
            }
            writer.WriteLine(time);
            writer.WriteLine(selfDefineErrorString);
            writer.WriteLine("异常信息：" + GetStackTraceModelName());
            writer.WriteLine("\r\n--------------------------------------\r\n");
            writer.Flush();
            writer.Dispose();
        }
    }
}
